/**
 * Copyright (C) 2008+ Spark Zheng
 *
 * @file	src/log.c
 * @brief
 *      A thread-safe log modle
 *      We May not use "log.h" directly, perfer to create an **_log.h,
 *      define LOG_NUM and log_arg in **_log.h.
 *
 * @see		dlib
 * @history
 *      version 0.0.1   Spark Zheng init log module, add syslog/streamlog
 *      version 0.0.2   Spark Zheng fixuped ctime bug.
 */

#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <sys/types.h>
#include "log.h"

/** global struct for log-functions */
dlib_log_t dlog;

int dlib_log_init(const char *ident, const char *path, uint32_t n,
		  dlib_log_args_t *args)
{
#ifndef _DLIB_LOG_USE_SYSLOG
	uint32_t i = 0;
	int len = 0;
	char log_file_dir[PATH_MAX];
	char log_file_full[PATH_MAX];

	if (path == NULL || ident == NULL || args == NULL || n == 0)
		return -1;

	while ((dlog.fp = malloc(n * sizeof (FILE *))) == NULL);
	while ((dlog.locks = malloc(n * sizeof (dlib_lock_t))) == NULL);

	len = snprintf(log_file_dir, PATH_MAX, "%s", path);
	while (i < n) {
		/* check the base_path first */
		if (args[i].log_file == NULL) {
			i++;
			continue;
		}

		if (len + strlen(args[i].log_file) >= PATH_MAX) {
			fprintf(stderr, "Log error, too long path %s.\n", path);
			if (dlog.fp != NULL)
				free(dlog.fp);
			if (dlog.locks != NULL)
				free(dlog.locks);
			return -2;
		}
		if (access(log_file_dir, F_OK) != 0) {
			if (mkdir(log_file_dir, 0755) != 0) {
				fprintf(stderr, "Log error, unable to mkdir %s: %s\n",
						log_file_dir, strerror(errno));
				if (dlog.fp != NULL)
					free(dlog.fp);
				if (dlog.locks != NULL)
					free(dlog.locks);
				return -10;
			}
		}

		snprintf(log_file_full, PATH_MAX, "%s/%s", path, args[i].log_file);
		DLOG_OPEN(i, ident, log_file_full);

		if (dlog.fp[i] == NULL) {
			fprintf(stderr, "Log error, unable to open %s: %s\n",
					log_file_full, strerror(errno));
			dlib_log_exit(n);
			return -10;
		}
		if (dlib_lock_init(&dlog.locks[i]) != 0) {
			fprintf(stderr, "Log error, locks initial error.\n");
			dlib_log_exit(n);
			return -11;
		}
		i++;
	} /* end while */
#else
	if (ident == NULL)
		return -1;
	UNUSED_PARAM(path);
	UNUSED_PARAM(n);
	UNUSED_PARAM(args);
	DLOG_OPEN(0, ident, NULL);
#endif
	return 0;
}

void dlib_log_exit(uint32_t n)
{
#ifdef _DLIB_LOG_USE_SYSLOG
	UNUSED_PARAM(n);
	DLOG_CLOSE(0);
#else
	uint32_t i = 0;
	while (i < n) {
		dlib_lock_lock(&dlog.locks[i]);
		DLOG_CLOSE(i);
		dlib_lock_unlock(&dlog.locks[i]);
		dlib_lock_exit(&dlog.locks[i]);
		i++;
	}
	if (dlog.fp != NULL)
		free(dlog.fp);
	if (dlog.locks != NULL)
		free(dlog.locks);
#endif
	return;
}
